<template>
  <view class="my-equi">
    <!-- 我的设备列表开始 -->
    <view class="title u-font-40 u-m-b-24 u-p-l-24"> 我的设备 </view>
    <view v-if="equi_list.length > 0" class="scroll-view u-p-24 u-m-b-24" scroll-y="true">
      <!-- 每一项开始 -->
      <view class="u-m-b-20" v-for="(item, index) in equi_list" :key="index">
        <view class="">
          <u-swipe-action
            :show="item.is_show"
            @click.stop="delEqui(index)"
            @open="showDel"
            :options="options"
            :index="index"
            btn-width="64"
          >
            <view
              class="eq-item bg-white u-p-l-24 u-p-t-32 u-p-r-24 u-p-b-32"
              @tap="connectEqui(item.info)"
            >
              <!-- 上面部分开始 -->
              <view class="item-top u-flex u-m-b-8">
                <view class="top-title"> 设备名称 </view>
                <view class="top-text black-color u-line-1 u-m-r-24 u-line-1">
                  {{ item.title }}
                </view>
                <view class="top-img u-flex u-col-center" @tap.stop="changeName(index)">
                  <image src="../../static/image/my/ic_xiugai@2x.png" mode=""></image>
                </view>
              </view>
              <!-- 上面部分结束 -->

              <!-- 下面部分开始 -->
              <view class="item-bottom u-flex">
                <view class="bottom-title"> 设备ID </view>
                <view class="bottom-text black-color u-line-1">
                  {{ item.eq_id }}
                </view>
              </view>
              <!-- 下面部分结束 -->
            </view>
          </u-swipe-action>
        </view>
      </view>
      <!-- 每一项结束 -->
    </view>
    <!-- 我的设备列表结束 -->
    <!-- 列表开始 -->
    <view class="title u-p-l-24 u-font-40"> 附近设备 </view>
    <view v-if="near_list.length > 0" class="scroll-view u-p-24" scroll-y="true">
      <!-- 每一项开始 -->
      <view
        class="u-m-b-20"
        v-for="(item, index) in near_list"
        :key="index"
        @click="connectEqui(item)"
      >
        <!-- <u-swipe-action
          :show="item.is_show"
          @click="delEqui(index)"
          @open="showDel"
          :options="options"
          :index="index"
          btn-width="64"
        > -->
        <view class="eq-item bg-white u-p-l-24 u-p-t-32 u-p-r-24 u-p-b-32">
          <!-- 上面部分开始 -->
          <view class="item-top u-flex u-m-b-8">
            <view class="top-title"> 设备名称 </view>
            <view class="top-text black-color u-line-1 u-m-r-24 u-line-1">
              {{ item.name }}
            </view>
            <!-- <view class="top-img u-flex u-col-center" @click="changeName(index)">
                <image src="../../static/image/my/ic_xiugai@2x.png" mode=""></image>
              </view> -->
          </view>
          <!-- 上面部分结束 -->

          <!-- 下面部分开始 -->
          <view class="item-bottom u-flex">
            <view class="bottom-title"> 设备ID </view>
            <view class="bottom-text black-color u-line-1">
              {{ item.deviceId }}
            </view>
          </view>
          <!-- 下面部分结束 -->
        </view>
        <!-- </u-swipe-action> -->
      </view>
      <!-- 每一项结束 -->
    </view>
    <!-- 列表结束 -->

    <!-- 列表空显示开始 -->
    <!-- <empty v-if="equi_list.length == 0" :tips="'还没有绑定设备哦~'"></empty> -->
    <!-- 列表空显示结束 -->

    <!-- popup弹出层开始 -->
    <u-popup v-model="pop_show" mode="center" border-radius="16" :closeable="true" width="602">
      <view class="pop-box u-p-l-40 u-p-r-40 u-p-t-28 u-p-b-42">
        <view class="title u-text-center u-m-b-38"> 修改设备名称 </view>
        <view class="textarea u-m-b-42">
          <textarea
            v-model="equi_name"
            class="u-p-l-40 u-p-t-26 u-p-r-40 u-p-b-26 w100"
            value=""
            placeholder="请输入设备名称～"
          />
        </view>
        <view class="tips u-m-b-42" style="color: red;">
          最大 7 个英文字母范围为大写 A 到小写 z
        </view>
        <view class="btn w100 u-p-t-22 u-p-b-22 u-text-center" @click="setName"> 确定 </view>
      </view>
    </u-popup>
    <!-- popup弹出层结束 -->

    <!-- 确认是否删除弹窗开始 -->
    <u-modal
      v-model="model_show"
      :content="model_content"
      :show-title="false"
      :show-cancel-button="true"
      @confirm="confirmDel"
    ></u-modal>
    <!-- 确认是否删除弹窗结束 -->
  </view>
</template>

<script>
  // import empty from '../../components/Empty.vue'
  export default {
    components: {
      // empty,
    },
    data() {
      return {
        // 删除弹窗状态
        model_show: false,
        // 删除提示内容
        model_content: '确定要删除当前设备吗？',
        // 要删除的下标
        del_index: 0,
        // pop状态
        pop_show: false,
        // 设备名称
        equi_name: '',
        // 设备index
        equi_index: 0,
        // 附近设备列表
        near_list: [],
        // 设备列表
        equi_list: [],
        // 按钮列表
        options: [
          {
            text: '删除',
            style: {
              backgroundColor: '#FF5D5D',
            },
          },
        ],
        // 设备id
        device_id: 0,
        // 设备名称
        device_name: '',
        // 服务id
        service_id: 0,
        // uuid
        uuid: 0,
        // 点击过来的type 1:智能训练 2:佩戴模式
        type: 0,
      }
    },
    methods: {
      // 蓝牙开始
      // 初始化蓝牙
      openBluetoothAdapter() {
        this.near_list = []
        uni.showLoading({
          title: '蓝牙初始化中',
        })
        uni.openBluetoothAdapter({
          success: (res) => {
            uni.hideLoading()
            this.showMsg('初始化成功')
            // 连接成功
            console.log('连接成功', res)
            // 扫描设备
            this.startBluetoothDevicesDiscovery()
          },
          fail: (res) => {
            this.showMsg('请打开蓝牙')
            uni.setStorageSync('is_connect', false)
            if (res.errCode === 10001) {
              uni.onBluetoothAdapterStateChange(function (res) {
                // 监听蓝牙适配器是否打开，若打开则自动搜索蓝牙设备(onBluetoothAdapterStateChange)
                if (res.available) {
                  console.log(res.available)
                  this.startBluetoothDevicesDiscovery()
                }
              })
            }
          },
        })
      },
      // 扫描设备
      startBluetoothDevicesDiscovery() {
        uni.startBluetoothDevicesDiscovery({
          allowDuplicatesKey: true,
          success: (res) => {
            // 监听扫描到的设备
            this.onBluetoothDeviceFound()
          },
        })
      },
      // 监听扫描到的设备
      onBluetoothDeviceFound() {
        uni.onBluetoothDeviceFound((res) => {
          res.devices.forEach((device) => {
            // 过滤掉没有名字的设备
            if (!device.name && !device.localName) return
            // 这么操作是为了去除重复
            const foundDevices = this.near_list // 将数据中的数组复制一份,利用动态绑定方式，不断复制最新的数组
            const idx = this.inArray(foundDevices, 'deviceId', device.deviceId)
            if (idx === -1) {
              this.near_list.push(device) // 数组里没有的的就向里面添加数据，保证没有重复[uni写法]
            }
          })
          // console.log(this.near_list)
        })
      },
      // 连接蓝牙设备
      connectEqui(e) {
        console.log('点击连接设备', e)
        uni.showLoading({
          title: '正在连接设备',
        })
        let obj = {}
        obj.title = e.name
        obj.eq_id = e.deviceId
        obj.is_show = false
        obj.info = e
        if (this.equi_list.length > 0) {
          let res = this.equi_list.some((item) => {
            return item.eq_id == e.deviceId
          })
          if (!res) {
            this.equi_list.push(obj)
          }
        } else {
          this.equi_list.push(obj)
        }
        // if (uni.getStorageSync('my_list').length > 0) {
        //   let my_list = uni.getStorageSync('my_list')
        //   my_list.forEach((item) => {
        //     if (item.eq_id == uni.getStorageSync('device_id')) {
        //       item.title = this.equi_name
        //     }
        //   })
        //   // uni.setStorageSync('device_name', this.equi_name)
        //   uni.setStorageSync('my_list', my_list)
        // } else {
        //   uni.setStorageSync('my_list', this.equi_list)
        // }
        uni.setStorageSync('my_list', this.equi_list)
        if (uni.getStorageSync('my_list').length > 0) {
          let my_list = uni.getStorageSync('my_list')
          my_list.forEach((item) => {
            if (item.eq_id == e.deviceId) {
              uni.setStorageSync('device_name', item.title)
            }
          })
        } else {
          uni.setStorageSync('device_name', e.name)
        }
        console.log('我的设备列表', this.equi_list)
        console.log('点击蓝牙设备', e)
        this.device_id = e.deviceId
        this.device_name = e.name
        uni.setStorageSync('device_id', e.deviceId)
        // 将设备名称也传递给全局变量
        uni.createBLEConnection({
          deviceId: this.device_id,
          success: (res) => {
            uni.setStorageSync('equi_list', this.equi_list)
            // this.connected = true,
            console.log('连接时获取设备id', this.device_id)
            setTimeout(() => {
              this.getBLEDeviceServices()
            }, 1000) // 这里必须要延迟才行这是一个bug
            console.log('连接设备成功', res)
            // 将设备id和名称给后台
            this.bindEqui(this.device_id, this.device_name)
            // this.stopBluetoothDevicesDiscovery() // 此时停止蓝牙搜索
            uni.setStorageSync('is_connect', true)
          },
          fail: (err) => {
            console.log('建立连接失败', err)
            if (uni.getStorageSync('is_connect')) {
              uni.showToast({
                title: '设备已连接',
                icon: 'none',
              })
            } else {
              uni.showToast({
                title: '建立连接失败',
                icon: 'none',
              })
            }
            return
          },
        })
      },
      // 获取设备信息
      getBLEDeviceServices() {
        uni.getBLEDeviceServices({
          deviceId: this.device_id,
          success: (res) => {
            for (let i = 0; i < res.services.length; i++) {
              if (res.services[i].isPrimary) {
                // 将服务id存储添加到全局服务id数组中
                this.service_id = res.services[i].uuid
                uni.setStorageSync('service_id', res.services[i].uuid)
                console.log(`服务id:${i}`, this.serviceId)
                this.getBLEDeviceCharacteristics() // 获取蓝牙设备某个服务中所有特征值
                return
              }
            }
          },
          fail: (err) => {
            uni.showToast({
              title: '获取服务失败',
              icon: 'none',
            })
            return
          },
        })
      },
      // 获取设备的所有特征值
      getBLEDeviceCharacteristics() {
        uni.getBLEDeviceCharacteristics({
          // 设备id与服务id必须要给,特征值id先不用获取，直接写死
          deviceId: this.device_id,
          serviceId: this.service_id,
          success: (res) => {
            uni.hideLoading()
            console.log('------该特征值可写', res)
            if (!res.characteristics[0].properties.write) {
              this.showMsg('设备连接错误')
              return
            }
            uni.showToast({
              title: '设备连接成功',
            })
            // 保存uuid
            this.uuid = res.characteristics[0].uuid
            uni.setStorageSync('uuid', res.characteristics[0].uuid)
            console.log('获取设备特征值', res)
            if (res.characteristics[0].properties.read) {
              console.log('该特征值可读')
              uni.readBLECharacteristicValue({
                deviceId: this.device_id,
                serviceId: this.service_id,
                characteristicId: res.characteristics[0].uuid,
              })
            }
            if (res.characteristics[0].properties.write) {
              // 调用写
              this.writeBLECharacteristicValue('0x5A 0x00 0x01 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0x55')
              if (this.type === '1') {
                this.jump(`/views/intelligent_training/intelligent_training`)
              } else if (this.type === '2') {
                this.jump(`/views/wear_model/wear_model`)
              }
            }
            // 确保对应服务id下的特征值id具备监听数据变化的特性
            if (
              res.characteristics[0].properties.notify ||
              res.characteristics[2].properties.indicate
            ) {
              uni.notifyBLECharacteristicValueChange({
                deviceId: this.device_id,
                serviceId: this.service_id,
                characteristicId: res.characteristics[0].uuid,
                state: true, // 是否启用notify通知
                success: (res) => {
                  console.log('通知启用(notifyBLECharacteristicValueChange)', res)
                },
              })
            }
          },
          fail(res) {
            console.log('获取蓝牙设备特征值失败(getBLEDeviceCharacteristics)', res)
          },
          complete: (res) => {
            console.log('连接完成后的返回值-----', res)
          },
        })

        // 操作之前先监听，保证第一时间获取数据（value就是特征值当前最新的值）
        // 监听低功耗蓝牙设备的特征值变化事件。必须先启用 notifyBLECharacteristicValueChange 接口才能接收到设备推送的 notification
        uni.onBLECharacteristicValueChange((res) => {
          console.log('特征值变化', res)
          // let str = parseInt(this.ab2hex(res.value), 16).toString(2)
          let str = this.ab2hex(res.value)
          uni.setStorageSync('val_change', str)
          console.log(str)
        })
      },
      // 停止搜索
      stopBluetoothDevicesDiscovery() {
        uni.stopBluetoothDevicesDiscovery()
        console.log('已停止蓝牙扫描(closeBluetoothAdapter)')
        uni.showToast({
          title: '蓝牙搜索已停止',
          icon: 'success',
        })
      },
      // 向蓝牙写入
      writeBLECharacteristicValue(str, text) {
        if (text) {
          uni.showLoading({
            title: text,
            mask: true,
          })
        }
        console.log('我正在发送数据【手机向蓝牙模块】')
        // 向蓝牙设备发送一个0x00的16进制数据//代表内存之中的一段二进制数据
        const buffer = this.hex2ab(str)
        uni.writeBLECharacteristicValue({
          deviceId: uni.getStorageSync('device_id'), // 设备deviceId
          serviceId: uni.getStorageSync('service_id'), // 设备service_id
          characteristicId: uni.getStorageSync('uuid'), // 设备write特征值
          value: buffer, // 写入数据
          success: (res) => {
            console.log('发送数据:', res)
            uni.hideLoading()
            this.showMsg('修改成功', 'success')
            this.equi_list[this.equi_index].title = this.equi_name
            uni.setStorageSync('device_name', this.equi_name)
            console.log(this.equi_list[this.equi_index].title)
            this.pop_show = false
            if (uni.getStorageSync('my_list').length > 0) {
              let my_list = uni.getStorageSync('my_list')
              my_list.forEach((item) => {
                if (item.eq_id == uni.getStorageSync('device_id')) {
                  item.title = this.equi_name
                }
              })
              uni.setStorageSync('my_list', my_list)
            }
          },
          fail: (err) => {
            this.showMsg('修改失败')
            this.pop_show = false
            console.log('err', err)
          },
        })
      },
      // 16进制字符串转ArrayBuffer示例
      hex2ab(str) {
        const typedArray = new Uint8Array(
          str.match(/[\da-f]{2}/gi).map(function (h) {
            return parseInt(h, 16)
          })
        )
        return typedArray.buffer
      },

      // ArrayBuffer转16进制字符串示例
      ab2hex(buffer) {
        const hexArr = Array.prototype.map.call(new Uint8Array(buffer), function (bit) {
          return ('00' + bit.toString(16)).slice(-2)
        })
        return hexArr.join('')
      },
      // 为了去除重复的
      inArray(arr, key, val) {
        for (let i = 0; i < arr.length; i++) {
          if (arr[i][key] === val) {
            return i
          }
        }
        return -1
      },
      // 点击修改设备名称
      changeName(index) {
        this.equi_name = ''
        this.pop_show = true
        this.equi_index = index
        this.equi_list.forEach((item) => {
          item.is_show && (item.is_show = false)
        })
      },
      // 点击确定修改
      setName() {
        if (!this.equi_name) {
          this.showMsg('请输入设备名称')
        } else {
          let reg = /^[a-zA-Z]{1,7}$/
          if (!reg.test(this.equi_name)) {
            this.showMsg('格式不正确')
            return
          }
          // 修改蓝牙名称
          this.codeChange(this.equi_name)
        }
      },
      // 将英文转为ASCII码
      codeChange(string) {
        let blue_arr = ['0xFF', '0xFF', '0xFF', '0xFF', '0xFF', '0xFF', '0xFF']
        let string_arr = string.split('')
        string_arr.forEach((item, index) => {
          blue_arr[index] = '0x' + item.charCodeAt().toString(16)
        })
        // let new_arr = string_arr.map((item) => {
        //   return item.charCodeAt().toString(16)
        // })
        blue_arr.unshift('0x5A')
        blue_arr.push('0x55')
        let blue_str = blue_arr.join(' ')
        this.writeBLECharacteristicValue(blue_str)
      },
      // 点击删除和一个显示其他隐藏
      delEqui(index) {
        this.model_show = true
        this.del_index = index
      },
      // 如果打开一个的时候，不需要关闭其他，则无需实现本方法
      showDel(index) {
        // 先将正在被操作的swipeAction标记为打开状态，否则由于props的特性限制，
        // 原本为'false'，再次设置为'false'会无效
        this.equi_list[index].is_show = true
        this.equi_list.map((val, idx) => {
          if (index != idx) this.equi_list[idx].is_show = false
        })
      },
      // 点击确定删除
      confirmDel() {
        let _this = this
        uni.closeBLEConnection({
          deviceId: uni.getStorageSync('device_id'),
          success: (res) => {
            _this.equi_list.splice(this.del_index, 1)
            uni.setStorageSync('is_connect', false)
            _this.showMsg('删除成功')
          },
          complete: (res) => {
            _this.equi_list.splice(this.del_index, 1)
            uni.setStorageSync('is_connect', false)
            _this.showMsg('删除成功')
          },
        })
      },
      // 将设备id和名称给后台
      async bindEqui(number, name) {
        const res = await this.$api.common.bindEqui('addMachine', {
          name,
          number,
        })
        if (res.code === 200) {
          uni.setStorageSync('member_machine_id', res.data.member_machine_id)
        }
        console.log('将设备id和名称给后台', res)
      },
      // 获取下载文件
      getBin() {
        uni.downloadFile({
          url: 'https://akhehuoren.oss-cn-hangzhou.aliyuncs.com/test.bin',
          success(res) {
            var filePath = res.tempFilePath
            console.log('下载文件', res)
            var pathArrayBuffer = wx.getFileSystemManager().readFileSync(filePath)
            var buf = new Uint8Array(pathArrayBuffer)
          },
        })
      },
    },
    onShow() {
      // 获取下载文件
      this.getBin()
      // 蓝牙初始化
      this.openBluetoothAdapter()
      // this.equi_list = uni.getStorageSync('equi_list')
      console.log(this.equi_list)
      uni.getStorageSync('my_list') && (this.equi_list = uni.getStorageSync('my_list'))
    },
    onLoad(options) {
      console.log(options)
      options.type && (this.type = options.type)
    },
  }
</script>

<style lang="scss">
  ::-webkit-scrollbar {
    width: 0;
    height: 0;
    color: transparent;
  }

  u-swipe-action {
    box-sizing: border-box;
  }

  .my-equi {
    width: 100%;
    height: 100%;

    .scroll-view {
      width: 100%;
      box-sizing: border-box;

      .eq-item {
        margin-bottom: 24rpx;
        border-radius: 8rpx;

        .top-title,
        .bottom-title {
          width: 120rpx;
          margin-right: 24rpx;
          font-family: PingFangSC-Regular, PingFang SC;
          font-size: 28rpx;
          font-weight: 400;
          color: #666;
        }

        .bottom-text {
          width: 500rpx;
        }

        .top-text {
          max-width: 400rpx;
        }

        .top-img {
          width: 24rpx;
          height: 24rpx;
        }
      }

      .eq-item:last-child {
        margin-bottom: 0;
      }
    }

    .pop-box {
      .title {
        font-family: PingFangSC-Medium, PingFang SC;
        font-size: 32rpx;
        font-weight: 500;
        color: #333;
      }

      .textarea {
        height: 456rpx;
        font-family: PingFangSC-Regular, PingFang SC;
        font-size: 28rpx;
        font-weight: 400;
        color: #999;
        border: 2rpx solid #e1e1e1;
        border-radius: 16rpx;

        textarea {
          height: 100%;
        }
      }

      .btn {
        font-family: PingFangSC-Regular, PingFang SC;
        font-size: 32rpx;
        font-weight: 400;
        color: #fff;
        background: linear-gradient(90deg, #97cefc 0%, #5690c1 100%);
        border-radius: 44rpx;
      }
    }
  }
</style>
